﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using FlexminAPI;
using System.Diagnostics;
using System.Threading;

namespace TaskManager
{
	public delegate void ProcessRefreshDelegate();

	public partial class TaskForm : Form
	{
		TaskSlave slave;
		Thread refreshThread;

		public TaskForm(ISlave slave)
		{
			InitializeComponent();
			this.slave = slave as TaskSlave;
			
			refreshThread = new Thread(new ThreadStart(RefreshThreadProc));
			refreshThread.Start();
		}

		private bool die = false;

		private void RefreshThreadProc()
		{
			while (!die)
			{
				LoadProcesses();
				Thread.Sleep(3000);
			}			
		}

		List<ProcessInfo> processesInfo = new List<ProcessInfo>();

		private void LoadProcesses()
		{
			if (this.InvokeRequired)
			{
				this.Invoke(new ProcessRefreshDelegate(LoadProcesses));
				return;
			}

			List<ProcessInfo> newProcessesInfo = new List<ProcessInfo>(this.slave.GetProcessesInfo());
			List<ProcessInfo> processesToAdd = new List<ProcessInfo>();
			List<ProcessInfo> processesToDelete = new List<ProcessInfo>();
			//listView1.BeginUpdate();

			bool found = false;
			for (int i = 0; i < newProcessesInfo.Count; i++)
			{
				found = false;

				for (int j = 0; j < processesInfo.Count; j++)
				{
					if (processesInfo[j].PID == newProcessesInfo[i].PID)
					{
						if (!processesInfo[j].Equals(newProcessesInfo[i]))
						{
							processesInfo[j] = newProcessesInfo[i];

							listView1.Items[j].SubItems[1].Text = processesInfo[j].PID.ToString();
							//listView1.Items[j].SubItems[2].Text = processesInfo[j].User;
							listView1.Items[j].SubItems[2].Text = processesInfo[j].Priority.ToString();
							//listView1.Items[j].SubItems[4].Text = processesInfo[j].CPU_Usage.ToString();
							listView1.Items[j].SubItems[3].Text = (processesInfo[j].Memory / 1024).ToString() + "k";
						}
						
						found = true;
						break;
					}
				}

				if (found)
					continue;

				processesToAdd.Add(newProcessesInfo[i]);				
			}

			for (int i = 0; i < processesInfo.Count; i++)
			{
				found = false;

				for (int j = 0; j < newProcessesInfo.Count; j++)
				{
					if (processesInfo[i].PID == newProcessesInfo[j].PID)
					{
						found = true;
						break;
					}
				}

				if (found)
					continue;

				processesToDelete.Add(processesInfo[i]);
			}

			foreach (ProcessInfo processInfo in processesToAdd)
			{
				processesInfo.Add(processInfo);

				ListViewItem item = new ListViewItem(processInfo.Name);
				item.SubItems.Add(processInfo.PID.ToString());
				//item.SubItems.Add(processInfo.User);
				item.SubItems.Add(processInfo.Priority.ToString());
				//item.SubItems.Add(processInfo.CPU_Usage.ToString());
				item.SubItems.Add((processInfo.Memory / 1024).ToString() + "k");

				listView1.Items.Add(item);
			}

			foreach (ProcessInfo processInfo in processesToDelete)
			{
				processesInfo.Remove(processInfo);
				for (int i = 0; i < listView1.Items.Count; i++)
				{
					if (listView1.Items[i].SubItems[1].Text == processInfo.PID.ToString())
					{
						listView1.Items.Remove(listView1.Items[i]);
						break;
					}
				}
			}
			//listView1.EndUpdate();
		}

		private void killToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (listView1.SelectedItems != null)
			{
				if (MessageBox.Show("Are you sure?", "Kill Process", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
				{
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.Kill(pid);
					}
				}
			}
		}

		private void toolStripComboBox2_SelectedIndexChanged(object sender, EventArgs e)
		{
			switch (toolStripComboBox2.SelectedIndex)
			{
				case 0:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.Idle);
					}
					break;
				case 1:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.BelowNormal);
					}
					break;
				case 2:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.Normal);
					}
					break;
				case 3:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.AboveNormal);
					}
					break;
				case 4:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.High);
					}
					break;
				case 5:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.RealTime);
					}
					break;
			}
			
			contextMenuStrip1.Close();			
		}

		private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
		{
			try
			{
				string priority = listView1.SelectedItems[0].SubItems[3].Text;
				for (int i = 1; i < listView1.SelectedItems.Count; i++)
					if (priority != listView1.SelectedItems[i].SubItems[3].Text)
						priority = "";
				switch (priority.ToLower())
				{
					case "idle":
						toolStripComboBox2.SelectedIndex = 0;
						break;
					case "belownormal":
						toolStripComboBox2.SelectedIndex = 1;
						break;
					case "normal":
						toolStripComboBox2.SelectedIndex = 2;
						break;
					case "abovenormal":
						toolStripComboBox2.SelectedIndex = 3;
						break;
					case "high":
						toolStripComboBox2.SelectedIndex = 4;
						break;
					case "realtime":
						toolStripComboBox2.SelectedIndex = 5;
						break;
				}
			}
			catch
			{
				toolStripComboBox2.SelectedText = "";
			}			
		}

		private void processToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
		{
			try
			{
				string priority = listView1.SelectedItems[0].SubItems[3].Text;
				for (int i = 1; i < listView1.SelectedItems.Count; i++)
					if (priority != listView1.SelectedItems[i].SubItems[3].Text)
						priority = "";
				switch (priority.ToLower())
				{
					case "idle":
						toolStripComboBox1.SelectedIndex = 0;
						break;
					case "belownormal":
						toolStripComboBox1.SelectedIndex = 1;
						break;
					case "normal":
						toolStripComboBox1.SelectedIndex = 2;
						break;
					case "abovenormal":
						toolStripComboBox1.SelectedIndex = 3;
						break;
					case "high":
						toolStripComboBox1.SelectedIndex = 4;
						break;
					case "realtime":
						toolStripComboBox1.SelectedIndex = 5;
						break;
				}
			}
			catch
			{
				toolStripComboBox2.SelectedText = "";
			}			
		}

		private void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
		{
			switch (toolStripComboBox1.SelectedIndex)
			{
				case 0:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.Idle);
					}
					break;
				case 1:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.BelowNormal);
					}
					break;
				case 2:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.Normal);
					}
					break;
				case 3:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.AboveNormal);
					}
					break;
				case 4:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.High);
					}
					break;
				case 5:
					foreach (ListViewItem item in listView1.SelectedItems)
					{
						int pid = int.Parse(item.SubItems[1].Text);
						slave.SetPriority(pid, ProcessPriorityClass.RealTime);
					}
					break;
			}

			processToolStripMenuItem.DropDown.Close();
		}

		private void TaskForm_FormClosing(object sender, FormClosingEventArgs e)
		{
			die = true;
		}
	}
}
